#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>
#include<errno.h>
#include<pthread.h>
//线程同步：条件变量实现生产者和消费者模型

//模拟生产和消费参数的任务链表
struct msg
{
    int num;
    struct msg*next;
};

struct msg *head=NULL;

//初始化互斥量和条件变量
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;

pthread_cond_t produceIsNotEmpty=PTHREAD_COND_INITIALIZER;

void * producer(void *arg)
{
    while(1)
    {


    struct msg*item;
    //模拟生产一个产品
    item=(struct msg*)malloc(sizeof(struct msg));

    item->num=rand()%1000+1;
    //加锁，访问共享资源
    pthread_mutex_lock(&mutex);


    item->next=head;
    head=item; //向公共资源添加数据
    
    
    pthread_mutex_unlock(&mutex);

    printf("produce %d\n",item->num);
    //唤醒阻塞在共享资源条件变量为空的线程
    pthread_cond_signal(&produceIsNotEmpty);

    sleep(rand()%3);//让消费者有充足的时间去获取资源
    
    }

    pthread_exit(0);
}

void * customer(void *arg)
{
    while(1)
    {

    
    //消费者尝试访问任务链表，刚开始任务链表为空
    //对共享区域访问先拿锁
    pthread_mutex_lock(&mutex);
    if(head==NULL)
    {
        pthread_cond_wait(&produceIsNotEmpty,&mutex);//阻塞等待 条件变量满足同时，释放锁
        //当条件满足时wait函数返回，同时加锁
    }

    struct msg* item;
    item=head;
    head=item->next;//对共享资源进行访问
    pthread_mutex_unlock(&mutex);

    printf("costomer %d\n",item->num);
    free(item);

    sleep(rand()%3);//确保生产者继续生产产品

    }
    pthread_exit(0);
}
int main(void)
{
    int ret;
    
    srand(time(NULL));
    pthread_t pid,cid;//生产者和消费者的线程id

    pthread_create(&pid,NULL,producer,NULL);
    pthread_create(&cid,NULL,customer,NULL);



    //线程执行结束，回收线程
    pthread_join(pid,NULL);
    pthread_join(cid,NULL);





    return 0;
}
